/* Copyright 2014 Jan Wolter */
#include "stack.h"
#include "bouquet.h"

/* Array of bouquet piles used in this game */
BouquetStack *bouquet;
int bouquetsize= 0;       /* current size of bouquet array */

/* If chunksize == 1, then every card is removable.
 *
 * If chunksize == 3, then we can play
 *    (A) the last card.
 *    (B) cards 2, 5, 8, ...
 *    (C) cards at top, top+3, top+6, ...
 * When we walk through all the moves, we will return them in that order.
 *
 * bouquet.top is the index of the card that was left on top of the stack 
 * the last time a card was removed.
 */

int bouquet_firstMove(Stack *stack, int *index1, int *len)
{
    if (stack->n == 0) return 0;
    *len= 1;
    *index1= stack->n - 1;
    return  1;
}

int bouquet_nextMove(Stack *stack, int *index1, int *len)
{
    *len= 1;

    /* if the last move was the last card, then it's time to start sequence B */
    int chunksize= bouquet[stack->tid].chunksize;
    if (*index1 == stack->n - 1)
    {
	*index1= chunksize - 1;
	if (stack->n > chunksize) return 1;
    }

    /* if we are in sequence B, return the next card */
    int top= bouquet[stack->tid].top;
    if (((*index1 + chunksize)%chunksize) == chunksize - 1)
    {
	(*index1)+= chunksize;
	if (*index1 < stack->n - 1) return 1;
	/* Failed to continue sequence B - start sequence C */
	if (top == stack->n - 1 ||
	    ((top + chunksize)%chunksize) == chunksize - 1) return 0;
	*index1= top;
	return 1;
    }

    /* If we are in sequence C, continue it */
    (*index1)+= chunksize;
    return (*index1 < stack->n - 1);
}

void makeBouquet(Stack *cards, int chunksize, int reverse)
{
    /* Make sure we have memory for another bouquet pile */
    if (bouquetsize == 0)
    {
	bouquetsize= 1;
	bouquet= (BouquetStack *)malloc(bouquetsize*sizeof(BouquetStack));
    }
    else if (nbouquet == bouquetsize)
    {
	bouquetsize+= 3;
	bouquet= (BouquetStack *)realloc(bouquet,
	    bouquetsize*sizeof(BouquetStack));
    }

    bouquet[nbouquet].chunksize= chunksize;
    bouquet[nbouquet].top= -1;

    /* We allocate enough memory to hold all the remaining cards */
    /* mayInsert is null since we can't move cards to the bouquet. */
    int i= bouquet[nbouquet].id= newStack(BOUQUET,nbouquet,cards->n,
	    NULL, bouquet_firstMove, bouquet_nextMove, NULL);
    appendStack(stacks+i, cards, reverse);

    nbouquet++;
}

void cleanBouquet()
{
    free(bouquet);
    nbouquet= bouquetsize= 0;
}

void printBouquet(FILE *f, Stack *stks)
{
    char label[8];
    for (int k= 0; k < nbouquet; k++)
    {
	sprintf(label,"B%02d", k+1);
	printStack(f, label, stks+bouquet[k].id);
    }
}

/* Remove cards from all bouquets and append them to the given stack */
void gatherBouquet(Stack *s)
{
    for (int k= 0; k < nbouquet; k++)
    {
	Stack *ws= stacks+bouquet[k].id;
	appendStack(s, ws, 1);
    }
}
